package core;

import java.nio.ByteBuffer;
import java.util.LinkedList;

import interfaces.*;

/**
 * Classe que implementa uma tarefa
 * 
 * @author robertow
 *
 */
public class Fibo3 implements IJob {

	int numero;
	long result;
	int subJobCount;
	int x;
	int workload;
	byte[] resultDesc;

	// Para setar o inicio da execução de um job
	long execBegin;

	// Para setar o tempo que este job levou para ser executado
	long execTime;

	// Identificação do worker que resolveu o job
	String workerIdSolvedJob;

	// Identificação do job pai
	String idParentJob;

	boolean remote;

	String jobId;

	public Fibo3(int n) {
		this.numero = n;
		// this.workload = numero;
		this.workload = (int) (Math.pow(1.5, n) * 0.001);
		this.result = -1;
		this.subJobCount = 0;
	}

	public Fibo3(byte[] resultDescription) {
		ByteBuffer buf = ByteBuffer.wrap(resultDescription);
		this.numero = buf.getInt();
		// this.workload = numero;
		this.workload = (int) (Math.pow(1.5, numero) * 0.001);
		this.result = -1;
		this.subJobCount = 0;
	}

	public Fibo3(String workerId, byte[] description) {
		ByteBuffer buf = ByteBuffer.wrap(description);
		this.result = buf.getLong();
		this.workerIdSolvedJob = workerId;
	}

	@Override
	public LinkedList<IJob> breakJob() {
		// TODO Auto-generated method stub
		LinkedList<IJob> jobs = new LinkedList<IJob>();

		IJob j1 = new Fibo(numero - 1);
		j1.setID(getID() + "A");
		j1.setParentJob(getID());
		jobs.add(j1);

		IJob j2 = new Fibo(numero - 2);
		j2.setID(getID() + "B");
		j2.setParentJob(getID());
		jobs.add(j2);

		this.result = 0;
		this.subJobCount = 2;
		return jobs;
	}

	@Override
	public byte[] getDescription() {
		// TODO Auto-generated method stub
		ByteBuffer buf = ByteBuffer.allocate(4);
		buf.putInt(numero);
		return buf.array();
	}

	@Override
	public void setID(String jobId) {
		// TODO Auto-generated method stub
		this.jobId = jobId;
	}

	@Override
	public String getID() {
		// TODO Auto-generated method stub
		return this.jobId;
	}

	@Override
	public void setWorkerIdSolvedJob(String workerId) {
		// TODO Auto-generated method stub
		this.workerIdSolvedJob = workerId;
	}

	@Override
	public String getWorkerIdSolvedJob() {
		// TODO Auto-generated method stub
		return this.workerIdSolvedJob;
	}

	@Override
	public void setWorkload(int workload) {
		// TODO Auto-generated method stub
		this.workload = workload;
	}

	@Override
	public int getWorkload() {
		// TODO Auto-generated method stub
		return this.workload;
	}

	@Override
	public void setRemote(boolean remote) {
		// TODO Auto-generated method stub
		this.remote = remote;
	}

	@Override
	public boolean isRemote() {
		// TODO Auto-generated method stub
		return remote;
	}

	@Override
	public boolean isSolved() {
		// TODO Auto-generated method stub
		if (subJobCount == 0) {
			return true;
		}
		return false;
	}

	@Override
	public byte[] getResultDescription() {
		// TODO Auto-generated method stub
		ByteBuffer buf = ByteBuffer.allocate(8);
		buf.putLong(result);
		return buf.array();
	}

	@Override
	public void setResultDescription(byte[] resultDesc) {
		ByteBuffer buf = ByteBuffer.wrap(resultDesc);
		result = buf.getLong();
	}

	@Override
	public void setSubResult(byte[] subResultDescription) {
		// TODO Auto-generated method stub
		ByteBuffer buf = ByteBuffer.wrap(subResultDescription);
		result += buf.getLong();
	}

	@Override
	public void solve() {
		// TODO Auto-generated method stub
		result = fibo(numero);
	}

	long fibo(int n) {
		if (n <= 3) {
			return n;
		} else if (n % 2 != 0) {
			return fibo(n - 1) + fibo(n - 2);
		} else {
			return fibo(n - 1) + fibo(n - 2) + fibo(n - 3);
		}
	}

	@Override
	public void setParentJob(String idParentJob) {
		// TODO Auto-generated method stub
		this.idParentJob = idParentJob;
	}

	@Override
	public String getParentJob() {
		// TODO Auto-generated method stub
		return this.idParentJob;
	}

	@Override
	public void setSubJobCount(int subJobCount) {
		// TODO Auto-generated method stub
		this.subJobCount -= subJobCount;
	}

	@Override
	public int getSubJobCount() {
		// TODO Auto-generated method stub
		return this.subJobCount;
	}

	@Override
	public void setExecBegin(long time) {
		this.execBegin = time;
	}

	@Override
	public long getExecBegin() {
		return this.execBegin;
	}

	@Override
	public void setExecTime(long time) {
		// TODO Auto-generated method stub
		this.execTime = time;
	}

	@Override
	public long getExecTime() {
		// TODO Auto-generated method stub
		return this.execTime;
	}

	@Override
	public void setNumero(int numero) {
		this.numero = numero;
	}

	@Override
	public int getNumero() {
		return this.numero;
	}

	@Override
	public void setResult(long result) {
		this.result = result;
	}

	@Override
	public long getResult() {
		return this.result;
	}
}
